package com.ews.onlineexchange.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;

import javax.enterprise.context.ConversationScoped;
import javax.enterprise.event.Event;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.OptimisticLockException;
import javax.persistence.Query;
import javax.persistence.Transient;
import javax.servlet.http.HttpServletResponse;

import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.NodeCollapseEvent;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.NodeUnselectEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.CheckboxTreeNode;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.TreeNode;

import com.ews.onlineexchange.controller.activitii.BpmHome;
import com.ews.onlineexchange.dao.SectorDao;
import com.ews.onlineexchange.model.AgentService;
import com.ews.onlineexchange.model.Attachment;
import com.ews.onlineexchange.model.BestTradeEvaluation;
import com.ews.onlineexchange.model.Bulletin;
import com.ews.onlineexchange.model.ChooseType;
import com.ews.onlineexchange.model.DataEntity;
import com.ews.onlineexchange.model.Image;
import com.ews.onlineexchange.model.LimitUnit;
import com.ews.onlineexchange.model.MainBusiness;
import com.ews.onlineexchange.model.QualificationCert;
import com.ews.onlineexchange.model.QualificationClass;
import com.ews.onlineexchange.model.QualificationGroup;
import com.ews.onlineexchange.model.QualificationLevel;
import com.ews.onlineexchange.model.QualificationTemplate;
import com.ews.onlineexchange.model.RejectRecord;
import com.ews.onlineexchange.model.Relation;
import com.ews.onlineexchange.model.RequireType;
import com.ews.onlineexchange.model.RequirementDefination;
import com.ews.onlineexchange.model.Sector;
import com.ews.onlineexchange.model.ServiceBuyer;
import com.ews.onlineexchange.model.ServiceSupplier;
import com.ews.onlineexchange.model.Trade;
import com.ews.onlineexchange.model.TradeReportData;
import com.ews.onlineexchange.model.TradeStatus;
import com.ews.onlineexchange.model.User;
import com.ews.onlineexchange.service.BestTradeEvaluationService;
import com.ews.onlineexchange.service.BulletinSeqNoGenerator;
import com.ews.onlineexchange.service.BulletinService;
import com.ews.onlineexchange.service.CandidateSupplierSelector;
import com.ews.onlineexchange.service.DeterminedRecordService;
import com.ews.onlineexchange.service.EntityHome;
import com.ews.onlineexchange.service.RejectRecordHome;
import com.ews.onlineexchange.service.SmsService;
import com.ews.onlineexchange.service.SupplierApplyService;
import com.ews.onlineexchange.service.TradeSeqNoGenerator;
import com.ews.onlineexchange.service.TradeService;
import com.ews.onlineexchange.service.UserService;
import com.ews.onlineexchange.service.comparator.MapKeyAscComparator;
import com.ews.onlineexchange.service.comparator.MapKeyDescComparator;
import com.ews.onlineexchange.service.qualifier.BestBulletinAgreeEvent;
import com.ews.onlineexchange.service.qualifier.BulletinAgreeEvent;
import com.ews.onlineexchange.service.qualifier.BulletinRejectEvent;
import com.ews.onlineexchange.util.AttachmentUtils;
import com.ews.onlineexchange.util.SystemUUIDUtil;
import com.ews.onlineexchange.vo.BulletinSelectItem;

@Named
@ConversationScoped
public class BulletinHome3 extends EntityHome<Bulletin, String> {

	private static final long						serialVersionUID		= 1L;
	
	@Inject
	UserService										userService;

	@Inject
	BulletinSeqNoGenerator							bulletinSeqNoGenerator;

	@Inject
	BulletinService									bulletinService;

	@Inject
	TradeSeqNoGenerator								tradeSeqNoGenerator;

	@Inject
	RejectRecordHome								rejectRecordHome;

	@Inject
	EntityManager									entityManager;

	@Inject
	DeterminedRecordService							recordService;

	@Inject
	ServiceSupplierHome								serviceSupplierHome;

	@Inject
	TradeService									tradeService;

	@Inject
	SmsService 										smsService;
	
	@Inject
	TimeCloseBulletinList							timeCloseBulletinList;

	@Inject
	SupplierApplyService							supplierApplyService;

	@Inject
	CandidateSupplierSelector						candidateSupplierSelector;
	
	@Inject
	@BulletinAgreeEvent
	Event<Bulletin>									bulletinAgreeEvent;
	
	@Inject
	BpmHome											bpmHome;

	@Inject
	RuntimeService									runtimeService;

	@Inject
	TaskService										taskService;
	
	private String									rejectReason;
	private ServiceSupplier							serviceSupplier;
	private Trade									bestChooseTrade;
	private Trade									assessChooseTrade;
	private Set<TreeNode>							checkboxSelectedNodes	= new HashSet<>();
	private String									sectorStr;
	private TreeNode[]								selectedNodes;
	private Trade									manualChooseTrade;
	private QualificationGroup						currGroup;
	private String									currGroupIndex;
	private QualificationTemplate					currTemplate;
	private String									currTemplateIndex;
	private Map<String, Map<String, TreeNode>>		rootNodeMap				= new LinkedHashMap<>();
	private Map<String, Map<String, TreeNode[]>>	selectedNodeMap			= new LinkedHashMap<>();

	private AgentService							currAgentService;
	private String									currAgentServiceIndex;

	private QualificationGroup						currServiceGroup;
	private String									currServiceGroupIndex;
	private Map<String, Map<String, AgentService>>	selectedAgentServiceMap	= new LinkedHashMap<>();

	private List<ServiceSupplier>					suppliers				= new ArrayList<>();

	private boolean									debug;

	private TreeNode								rootNode;
	
	private Date									lastBuyerUpdateTime;
	
	private String									successTradeId;
	
	private String									conflictBulletinId;
	
	private String									refuseReason;

	public TreeNode getRootNode() {
		if ( rootNode == null ) {
			initRootNode();
		}
		return rootNode;
	}

	public void setRootNode( TreeNode rootNode ) {
		this.rootNode = rootNode;
	}

	@Override
	public void initConversation() {
		super.initConversation();
		conversation.setTimeout( 1000 * 60 * 20 );
		List<QualificationGroup> serviceGroups = getInstance().getQualificationGroup().getAgentServiceGroups();
		if ( serviceGroups.size() > 0 && StringUtils.isBlank( getCurrServiceGroupIndex() ) ) {
			setCurrServiceGroupIndex( serviceGroups.get( 0 ).getGroupIndex() );
		}
		if ( serviceGroups.size() > 0 ) {
			List<AgentService> services = serviceGroups.get( 0 ).getAgentServices();
			if ( services.size() > 0 && StringUtils.isBlank( getCurrAgentServiceIndex() ) ) {
				setCurrAgentServiceIndex( services.get( 0 ).getServiceIndex() );
			}
		}

		List<QualificationGroup> qualificationGroups = getInstance().getQualificationGroup().getQualificationGroups();
		if ( qualificationGroups.size() > 0 && StringUtils.isBlank( getCurrGroupIndex() ) ) {
			setCurrGroupIndex( qualificationGroups.get( 0 ).getGroupIndex() );
		}
		if ( qualificationGroups.size() > 0 ) {
			List<QualificationTemplate> templates = qualificationGroups.get( 0 ).getQualificationTemplates();
			if ( templates.size() > 0 && StringUtils.isBlank( getCurrTemplateIndex() ) ) {
				setCurrTemplateIndex( templates.get( 0 ).getTemplateIndex() );
			}
		}

	}

	@Override
	public Bulletin createInstance() {
		Bulletin instance = super.createInstance();
		// instance.setQualificationTemplate(new QualificationTemplate());
		// instance.addEmptyAllMatchGroup();
		if ( null == instance.getQualificationGroup() )
			instance.setQualificationGroup( new QualificationGroup() );
		instance.getQualificationGroup().setRequireType( RequireType.QualificationRequirement );
		instance.getQualificationGroup().setAgentServices( new ArrayList<AgentService>() );
		if ( isDebug() )
			debug( instance );

		return instance;
	}

	@Override
	public Bulletin loadInstance(){
		Bulletin instance =  super.loadInstance();
		instance.getQualificationGroup().initSubGroups();
		setOldChooseTime(instance.getChooseTime());
		setLastBuyerUpdateTime(instance.getBuyerLastUpdateTime());
		instance.getDefs().stream().forEach(def->{
			def.setUuid(SystemUUIDUtil.getUUID());
		});
		return instance;
	}

	private void debug( Bulletin instance ) {
		String randomSuffix = getRandomSuffix( 10000000 );
		instance.setProjectName( "测试工程项目".concat( randomSuffix ) );
		instance.setAmountOfInvestment( new BigDecimal( 100000 ) );
		instance.setPrice(new BigDecimal(50000.1));
		instance.setPriceRemark( "服务金额高阔：1、2、3、4、5、6" );
		instance.setProjectInfo( "ProjectInfo" );
		instance.setContent( "Content" );
		instance.setLimitOfTime( 3 );
		instance.setLimitUnit( LimitUnit.Month );
		instance.setLimitRemark( "limitRemark" );
		instance.setWayOfPayment( "WayOfPayment" );
		instance.setWayOfChoose( ChooseType.Random );
//		Calendar calendar = Calendar.getInstance();
//		calendar.add( Calendar.MINUTE, 3 );
//		instance.setEndingApplyTime( calendar.getTime() );
		instance.setAddressOfChoose( "addressOfChoose" );
//		calendar.add( Calendar.MINUTE, 3 );
//		instance.setChooseTime( calendar.getTime() );
		instance.setTeleOfConsult( "13333333333" );
		instance.setTeleOfSupervise( "13333333333" );
	}

	private String getRandomSuffix( int multi ) {
		return new Integer( (int) (Math.random() * multi) ).toString();
	}
	
	@Inject
	BulletinList bulletinList;
	public List<BulletinSelectItem> filterBulletin(String query) {
		if ( StringUtils.isBlank( query ) ) {
			return null;
		}
		
		return bulletinService.getBulletinProjectMap( query );
        
	}
	
	@Override
	public String saveAndFlush() {
		try {
			
			/*
			 * 选取时间不得与任意一个项目的选取时间相差10分钟以内
			 * 注:择优、评审 不判断
			 */
			if ( !this.isDebug() ) {

			}
			
			
			if ( getInstance().getAuditResult() != null && getInstance().getAuditResult()) {
				FacesContext.getCurrentInstance().addMessage( "",
						new FacesMessage( FacesMessage.SEVERITY_ERROR, "公告已经审核通过，不能进行修改！", "" ) );
				return null;
			}
			
			if ( getInstance().getPhotos().size() == 0 ) {
				FacesContext.getCurrentInstance().addMessage( "photos",
						new FacesMessage( FacesMessage.SEVERITY_ERROR, "请上传交易申请表！", "" ) );
				return null;
			}
			
			getInstance().getQualificationGroup().setBulletin(getInstance());
			List<QualificationGroup> qualificationGroups = getInstance().getQualificationGroup().getQualificationGroups();
			List<QualificationGroup> serviceGroups = getInstance().getQualificationGroup().getAgentServiceGroups();
			if ( serviceGroups.size() == 0 && qualificationGroups.size() == 0 ) {
				FacesContext.getCurrentInstance().addMessage( "",
						new FacesMessage( FacesMessage.SEVERITY_ERROR, "请选择一种公告要求！", "" ) );
				return null;
			}
			for ( QualificationGroup qualificationGroup : serviceGroups ) {
				List<AgentService> agentServices = qualificationGroup.getAgentServices();
				for ( AgentService agentService : agentServices ) {
					if ( StringUtils.isBlank( agentService.getId() ) ) {
						FacesContext.getCurrentInstance().addMessage( "",
								new FacesMessage( FacesMessage.SEVERITY_ERROR, "请选择服务事项！", "" ) );
						return null;
					}
				}
			}

			if ( qualificationGroups.size() > 0 ) {
				for ( QualificationGroup qualificationGroup : qualificationGroups ) {
					List<QualificationTemplate> templates = qualificationGroup.getQualificationTemplates();
					for ( QualificationTemplate qualificationTemplate : templates ) {
						if ( qualificationTemplate.getSectors().size() == 0 ) {
							FacesContext.getCurrentInstance().addMessage( "",
									new FacesMessage( FacesMessage.SEVERITY_ERROR, "请选择行业范围！", "" ) );
							return null;
						}
					}
				}
			}

			StringBuilder sb = new StringBuilder();
			if ( qualificationGroups.size() > 0 ) {
				for ( QualificationGroup qualificationGroup : qualificationGroups ) {
					for ( QualificationTemplate template : qualificationGroup.getQualificationTemplates() ) {
						sb.append( template.getQualificationClass().getName() );
						sb.append( "、" );
					}
				}
			}
			if ( serviceGroups.size() > 0 ) {
				for ( QualificationGroup qualificationGroup : serviceGroups ) {
					List<AgentService> services = qualificationGroup.getAgentServices();
					for ( AgentService agentService : services ) {
						sb.append( agentService.getName() );
						sb.append( "、" );
					}
				}
				sb = new StringBuilder( sb.substring( 0, sb.length() - 1 ) );
			} else {
				if ( sb.length() > 0 )
					sb = new StringBuilder( sb.substring( 0, sb.length() - 1 ) );
			}
			getInstance().setBulletinReqStr( sb.toString() );

			if ( !isManaged() ) {
				getInstance().setSerialNumber( bulletinSeqNoGenerator.getNextSeqNo() );
				// getInstance().setQualificationTemplate(getTemplate());
				User user = userService.getLoginedUser();
				ServiceBuyer buyer = (ServiceBuyer) user;
				getInstance().setBuyer( buyer );
			}

			List<QualificationGroup> groups_inital = getInstance().getQualificationGroup().getGroups();// 原始的groups
			// getInstance().getQualificationGroup().getAgentServiceGroups().addAll(getInstance().getQualificationGroup().getQualificationGroups())
			Collection<QualificationGroup> groups_collection = CollectionUtils.union( serviceGroups, qualificationGroups );
			List<QualificationGroup> groups = new ArrayList<QualificationGroup>(
					new HashSet<QualificationGroup>( groups_collection ) );
			// 获取需要删除的groups
			Collection<QualificationGroup> removeGoups = CollectionUtils.subtract( groups_inital, groups );
			for ( QualificationGroup qualificationGroup : removeGoups ) {
				getEntityManager().remove( qualificationGroup );
				getInstance().getQualificationGroup().getGroups().remove( qualificationGroup );
			}
			getInstance().getQualificationGroup().setGroups( groups );
			// 当公告审核失败后，再次编辑的时候，将审核标志重置为null
			if ( getInstance().getAuditResult() != null && !getInstance().getAuditResult() ) {
				getInstance().setAuditResult( null );
				getInstance().setCurrRejectRecord( null );
				getInstance().setAuditTime( null );
			}
			
			/*
			 * 记录保存时间
			 */
			getInstance().setBuyerLastUpdateTime( new Date() );
			
			/*
			 * 如果选择了互斥公告，填充互斥公告字段
			 */
			if ( StringUtils.isNotBlank( getConflictBulletinId() ) ) {
				Bulletin conflictBulletin = bulletinService.getBulletinById( getConflictBulletinId() );
				if ( conflictBulletin.getConflictingBulletin() == null ) {
					getInstance().setConflictingBulletin( conflictBulletin );
				} else {getInstance().setConflictingBulletin( conflictBulletin.getConflictingBulletin() );
					
				}
			}

			return super.saveAndFlush();
		} catch (OptimisticLockException e) {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "公告状态已被其他人修改，请刷新页面后再进行修改提交！", "" ) );
			return null;
		}
		
	}

	public String saveManual() {
		if ( !isManaged() ) {
			getInstance().setSerialNumber( bulletinSeqNoGenerator.getNextSeqNo() );// 新增的时候，设置sno
			User user = userService.getLoginedUser();
			ServiceBuyer buyer = (ServiceBuyer) user;
			getInstance().setBuyer( buyer );
		}

		// 当公告审核失败后，再次编辑的时候，将审核标志重置为null
		if ( null != getInstance().getAuditResult() && !getInstance().getAuditResult() ) {
			getInstance().setAuditResult( null );
		}

		if ( !isManaged() ) {
			Trade successTrade = new Trade();
			successTrade.setSupplier( serviceSupplier );
			successTrade.setBulletin( getInstance() );
			successTrade.setSerialNumber( tradeSeqNoGenerator.getNextSeqNo() );
			// getInstance().setQualificationTemplate(getTemplate());
			getInstance().setSuccessTrade( successTrade );
		} else {
			Trade successTrade = getInstance().getSuccessTrade();
			successTrade.setSupplier( serviceSupplier );
		}
		getInstance().setEndingApplyTime( new Date() );
		getInstance().setChooseTime( new Date() );
		return super.saveAndFlush();
	}

	// public QualificationTemplate getTemplate(){
	// TreeNode[] nodes = getSelectedNodes();
	// TreeNode[] destNodes = null;
	// //去除行业根节点
	// if(nodes.length >0) {
	// TreeNode firstNode = nodes[0];
	// Sector sector = entityManagerDao.find(Sector.class,
	// ((Map<String,String>)firstNode.getData()).get("id"));
	// if (null == sector.getParentSector()) {
	// destNodes = new TreeNode[nodes.length - 1];
	// System.arraycopy(nodes, 1, destNodes, 0, nodes.length - 1);
	// } else {
	// destNodes = nodes;
	// }
	// }
	// QualificationTemplate template = getCurrTemplate();
	// List<Sector> sectors = new ArrayList<>();
	// for(TreeNode node :destNodes) {
	// Map<String, String> map = (Map<String, String>) node.getData();
	// Sector sector = entityManagerDao.find(Sector.class, map.get("id"));
	// sectors.add(sector);
	// }
	// template.setSectors(null);
	// template.setSectors(sectors);
	// return template;
	// }

	@Override
	public String delete() {

		getInstance().setDelFlag( DataEntity.DEL_FLAG_DELETE );
		return super.saveAndFlush();
	}

	public void initRootNode() {
		Map<String, TreeNode> _nodeMap = null;
		if ( getRootNodeMap().get( getCurrGroupIndex() ) == null ) {
			_nodeMap = new LinkedHashMap<String, TreeNode>();
			getRootNodeMap().put( getCurrGroupIndex(), _nodeMap );
		} else {
			_nodeMap = getRootNodeMap().get( getCurrGroupIndex() );
		}

		TreeNode rootNode = null;
		if ( _nodeMap.get( getCurrTemplateIndex() ) == null ) {
			rootNode = getRootSectorNode();
			_nodeMap.put( getCurrTemplateIndex(), rootNode );
		}
	}

	@Inject
	SectorDao sectorDao;

	private TreeNode getRootSectorNode() {
		if ( getCurrGroup() == null )
			return null;

		TreeNode rootNode = new CheckboxTreeNode( getSectorMap( null, "行业列表", null ), null );
		Map<String, TreeNode> tnMap = new LinkedHashMap<>();

		for ( Sector sector : getCurrTemplate().getQualificationClass().getRootSectors() ) {
			List<Object[]> sectorList = sectorDao.querySectorInTree( sector.getId() );
			for ( Object[] objects : sectorList ) {
				String id = (String) objects[0];
				String name = (String) objects[1];
				String parentId = (String) objects[2];

				TreeNode tn = null;
				TreeNode parentNode = tnMap.get( parentId );
				if ( parentNode != null ) {
					tn = new CheckboxTreeNode( getSectorMap( id, name, parentId ), parentNode );
				} else {
					tn = new CheckboxTreeNode( getSectorMap( id, name, parentId ), rootNode );
					rootNode.getChildren().add( tn );
				}
				tnMap.put( id, tn );
			}
		}

		return rootNode;
	}

	private Object getSectorMap( String id, String name, String parentId ) {
		Map<String, String> sectorFieldMap = new HashMap<>();
		sectorFieldMap.put( "id", id );
		sectorFieldMap.put( "name", name );
		sectorFieldMap.put( "parentId", parentId );
		return sectorFieldMap;
	}

	public void onNodeExpand( NodeExpandEvent event ) {
	}

	public void onNodeCollapse( NodeCollapseEvent event ) {
	}

	// public boolean isExistInSectors(String sector_id) {
	// Sector sector = entityManagerDao.find(Sector.class, sector_id);
	// List<Sector> sectors = getCurrTemplate().getSectors();
	// if (sectors.contains(sector))
	// return true;
	// else
	// return false;
	//
	// }

	public void onNodeSelect( NodeSelectEvent event ) {
		TreeNode selectedNode = event.getTreeNode();
		selectedNode.setSelected( true );
		List<TreeNode> childNodes = event.getTreeNode().getChildren();
		checkboxSelectedNodes.add( selectedNode );
		if ( childNodes.size() > 0 ) {
			selectedNode.setExpanded( true );
			checkboxSelectedNodes.addAll( childNodes );
			for ( TreeNode node : childNodes ) {
				node.setSelected( true );
				List<TreeNode> childNodes_1 = node.getChildren();
				if ( childNodes_1.size() > 0 ) {
					checkboxSelectedNodes.addAll( childNodes_1 );
				}
			}
		}
	}

	public void onNodeUnselect( NodeUnselectEvent event ) {
		TreeNode selectedNode = event.getTreeNode();
		selectedNode.setSelected( false );
		List<TreeNode> childNodes = event.getTreeNode().getChildren();
		checkboxSelectedNodes.remove( selectedNode );
		if ( childNodes.size() > 0 ) {
			checkboxSelectedNodes.removeAll( childNodes );
			for ( TreeNode node : childNodes ) {
				List<TreeNode> childNodes_1 = node.getChildren();
				if ( childNodes_1.size() > 0 )
					checkboxSelectedNodes.removeAll( childNodes_1 );
			}

		}
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService( UserService userService ) {
		this.userService = userService;
	}

	public String audit() {
		Bulletin bulletin = getInstance();
//		if(bulletin.getAuditResult() ) {
//			FacesContext.getCurrentInstance().addMessage( "",
//					new FacesMessage( FacesMessage.SEVERITY_ERROR, "此公告已经审核过了，请勿重复审核！", "" ) );
//			return null;
//		}
		
		/*
		 * refresh the entity
		 */
		if ( getEndingApplyTime().getTime() >= getChooseTime().getTime() ) {
			FacesContext.getCurrentInstance().addMessage( "bulletinEndingApplyTime",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "截止申请时间不能晚于选取时间！", "" ) );
			return null;
		}	
		if ( getEndingApplyTime().getTime() < new Date().getTime() ) {
			FacesContext.getCurrentInstance().addMessage( "bulletinEndingApplyTime",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "截止申请时间不能早于当前时间！", "" ) );
			return null;
		}	
		getEntityManager().refresh(bulletin);
		
		/*
		 * 判断是否在审核过程中被更新
		 */
		if ( getInstance().getBuyerLastUpdateTime() != null && getLastBuyerUpdateTime() != null && getInstance().getBuyerLastUpdateTime().after( getLastBuyerUpdateTime() ) ) {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "公告信息已被更新，请重新刷新页面后审核！", "" ) );
			if ( !conversation.isTransient() ) {
				conversation.end();				
			}
			return null;
		}
		
		bulletin.setEndingApplyTime( getEndingApplyTime() );
		bulletin.setChooseTime( getChooseTime() );
		
		return bulletinService.audit( bulletin );
	}

	public String unaudit() {
		Bulletin bulletin = getInstance();
		return bulletinService.unaudit( bulletin );
	}

	public String auditCancelSuccessBulletin() {
		Bulletin bulletin = getInstance();
		return bulletinService.auditCancelSuccessBulletin( bulletin );
	}
	public String auditBestChoose() {
		Bulletin bulletin = getInstance();
		
		/*
		 * 增加发布标志修改功能,标志位决定是否完成选取
		 */
		bulletin.setPublished( true );
		/*
		 * 将原前台选择中介的功能改为,通过后台评分自行判断
		 */
		
		Trade highScoreTrade = getHighScoreTrade();
		
		taskService.claim( bpmHome.getTaskId(), userService.getLoginedUser().getUsername() );
		Map<String, Object> variables = new HashMap<>();
		variables.put( "approvalResult", true );
		variables.put( "refuseReason", getRefuseReason() );
		taskService.setVariablesLocal(bpmHome.getTaskId(), variables);
		taskService.complete( bpmHome.getTaskId(), variables  );
		
		String auditBestChoose = bulletinService.auditBestChoose( bulletin, highScoreTrade );
		
		return "process/bestChooseEvaluationTaskList.xhtml?faces-redirect=true";
	}
	
	
	/**
	 * 根据评分结果,自动选出得分最高的候选交易
	 * 先由采购人打分，分数最高中选；如果分数相同，再看报价（报价低的中选）；如果报价相同，再根据信用分值区分，如果信用分值相同，再随机，再由管理员审核发布。
	 * @return
	 */
	@Transient
	public Trade getHighScoreTrade() {
		return getBestTradeForBulletin(getInstance().getBestTrades());
	}
	
	public  Trade  getBestTradeForBulletin(List<Trade> sortedTrades) {
		Map<BigDecimal, List<Trade>> scoreMap = getMapFormList(sortedTrades, "sumScore");
		
		Map<BigDecimal, List<Trade>> sortedScoreMap = sortMapByKey(scoreMap,"desc");
		List<Trade> highSumScoreTradeList = getFirstOrNull(sortedScoreMap);		
		if(highSumScoreTradeList.size() == 1) return highSumScoreTradeList.get(0);
		else {
			//判断报价
			Map<BigDecimal, List<Trade>> offerMap = getMapFormList(highSumScoreTradeList, "tradeReportData.offer");
			Map<BigDecimal, List<Trade>> sortedOfferMap = sortMapByKey(offerMap,"asc");
			List<Trade> highOfferTradeList = getFirstOrNull(sortedOfferMap);	
			if(highOfferTradeList.size() == 1)return highOfferTradeList.get(0);
			else {
				//判断信用分值
				Map<BigDecimal, List<Trade>> creditScoreMap = getMapFormList(highSumScoreTradeList, "supplier.creditScore");
				Map<BigDecimal, List<Trade>> sortedCreditScoreMap = sortMapByKey(creditScoreMap,"desc");
				List<Trade> creditScoreTradeList = getFirstOrNull(sortedCreditScoreMap);	
				if(creditScoreTradeList.size() == 1)return creditScoreTradeList.get(0);
				else {
					int size = creditScoreTradeList.size();
					 Random r=new Random();
					 System.out.println(r.nextInt(size));
					 return creditScoreTradeList.get(r.nextInt(size));
				}
			}
		}
	}
	
	
	
	public static void main(String[] args) {
		
		List<Trade> trades = new ArrayList<>();
		Trade trade = new Trade();
		ServiceSupplier supplier = new ServiceSupplier();
		supplier.setCreditScore(new BigDecimal(60));
		trade.setSupplier(supplier);
		List<BestTradeEvaluation> evs = new ArrayList<>();
		BestTradeEvaluation ev = new BestTradeEvaluation();
		ev.setScore(new BigDecimal(10.2).setScale(2,RoundingMode.HALF_UP));
		evs.add(ev);
		trade.setBestTradeEvaluations(evs);
		TradeReportData tradeReportData = new TradeReportData();
		tradeReportData.setOffer(new BigDecimal(2000.91));
		tradeReportData.setOfferScore(new BigDecimal(2));
		trade.setTradeReportData(tradeReportData);
		trades.add(trade);
		
		trade = new Trade();
		supplier = new ServiceSupplier();
		supplier.setCnname("win2");
		supplier.setCreditScore(new BigDecimal(70));
		trade.setSupplier(supplier);
		evs = new ArrayList<>();
		ev = new BestTradeEvaluation();
		ev.setScore(new BigDecimal(11.2).setScale(2,RoundingMode.HALF_UP));
		evs.add(ev);
		trade.setBestTradeEvaluations(evs);
		tradeReportData = new TradeReportData();
		tradeReportData.setOffer(new BigDecimal(2000.91));
		tradeReportData.setOfferScore(new BigDecimal(2));
		trade.setTradeReportData(tradeReportData);
		trades.add(trade);
		
		trade = new Trade();
		supplier = new ServiceSupplier();
		supplier.setCnname("win1");
		supplier.setCreditScore(new BigDecimal(70));
		trade.setSupplier(supplier);
		evs = new ArrayList<>();
		ev = new BestTradeEvaluation();
		ev.setScore(new BigDecimal(11.2).setScale(2,RoundingMode.HALF_UP));
		evs.add(ev);
		trade.setBestTradeEvaluations(evs);
		tradeReportData = new TradeReportData();
		tradeReportData.setOffer(new BigDecimal(2000.91));
		tradeReportData.setOfferScore(new BigDecimal(2));
		trade.setTradeReportData(tradeReportData);
		trades.add(trade);
		
		trade = new Trade();
		supplier = new ServiceSupplier();
		supplier.setCreditScore(new BigDecimal(60));
		trade.setSupplier(supplier);
		evs = new ArrayList<>();
		ev = new BestTradeEvaluation();
		ev.setScore(new BigDecimal(11.2).setScale(2,RoundingMode.HALF_UP));
		evs.add(ev);
		trade.setBestTradeEvaluations(evs);
		tradeReportData = new TradeReportData();
		tradeReportData.setOffer(new BigDecimal(2001.91));
		tradeReportData.setOfferScore(new BigDecimal(2));
		trade.setTradeReportData(tradeReportData);
		trades.add(trade);
		
//		Trade bestTradeForBulletin = getBestTradeForBulletin(trades);
//		System.out.println(bestTradeForBulletin.getSupplier().getCnname());
	}
	
	@Inject
	BestTradeEvaluationService bestTradeEvaluationService;
	public  Map  getMapFormList(List<Trade> trades,String column) {
		Map<BigDecimal, List<Trade>> map = new HashMap<BigDecimal, List<Trade>>();
		for (Trade trade : trades) {
			if("sumScore".equals(column)) {
				List<BestTradeEvaluation> list = bestTradeEvaluationService.getBestTradeEvaluationListByTrade(trade.getId());
				trade.setBestTradeEvaluations(list);
			}
			BigDecimal val;
			try {
				val = new BigDecimal(BeanUtils.getProperty(trade, column));
				if(map.get(val) == null) {
					List<Trade> trs = new ArrayList<>();
					trs.add(trade);
					map.put(val, trs);
				}else {
					map.get(val).add(trade);
				}
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return map;
	}
	
	
	private static List<Trade> getFirstOrNull(Map<BigDecimal, List<Trade>> map) {
		List<Trade> obj = null;
        for (Entry<BigDecimal, List<Trade>> entry : map.entrySet()) {
            obj = entry.getValue();
            if (obj != null) {
                break;
            }
        }
        return  obj;
    }
	
	public static Map<BigDecimal, List<Trade>> sortMapByKey(Map<BigDecimal, List<Trade>> map,String sort) {
		if (map == null || map.isEmpty()) {
			return null;
		}
		Map<BigDecimal, List<Trade>> sortMap = null;
		if("desc".equals(sort))sortMap =  new TreeMap<BigDecimal, List<Trade>>(new MapKeyDescComparator());
		else sortMap = new TreeMap<BigDecimal, List<Trade>>(new MapKeyAscComparator());	
		sortMap.putAll(map);
 
		return sortMap;
	}
	
	
	public String refuseBestChoose() {
		taskService.claim( bpmHome.getTaskId(), userService.getLoginedUser().getUsername() );
		Map<String, Object> variables = new HashMap<>();
		variables.put( "approvalResult", false );
		variables.put( "refuseReason", getRefuseReason() );
		taskService.setVariablesLocal(bpmHome.getTaskId(), variables);
		taskService.complete( bpmHome.getTaskId(), variables  );
		return "process/bestChooseEvaluationTaskList.xhtml?faces-redirect=true";
	}

	public String auditAssessChoose() {
		Bulletin bulletin = getInstance();
		
		if ( getInstance().getAssessAttachments().size() == 0 && getInstance().getAssessImages().size() == 0 ) {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "您没有上传任何公示材料！", "" ) );
			return null;
		}
		
		/*
		 * 增加发布标志修改功能,标志位决定是否完成选取
		 */
		bulletin.setPublished( true );
		
		/*
		 * 将原前台选择中介的功能改为,通过后台评分自行判断
		 */
		Trade successTrade = tradeService.getTradeById( this.getSuccessTradeId() );
		
		String result = bulletinService.auditAssessChoose( bulletin, successTrade  );
		if ( "auditted".equals( result ) ) {
			return "AssessChooseList.xhtml?faces-redirect=true&amp;includeViewParams=true";
		} else {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "此公告已经审核过了！", "" ) );
			return null;
		}
	}
	
	@Transient
	public void removeRequirementDefination(int index) {
		getInstance().getDefs().remove(index);
	}
	
	@Transient
	public void addRequirementDefination() {
		getInstance().getDefs().add(new RequirementDefination());
	}
	//重新选取功能
	private Date oldChooseTime;
	public String rechoose() {
		Bulletin bulletin = getInstance();
		if(bulletin.getChooseTime().before(new Date())) {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "选取时间不能早于当前时间！", "" ) );
			return null;
		}
		if(bulletin.getTradeStatus() != TradeStatus.Agreed) {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "此公告尚未成交，不能重新选取！", "" ) );
			return null;
		}
		
		/*
		 * 选取时间不得与任意一个项目的选取时间相差10分钟以内
		 * 注:择优不判断
		 */		
//		timeCloseBulletinList.refresh();
//		timeCloseBulletinList.setChooseTime( getInstance().getChooseTime() );
//		if ( timeCloseBulletinList.getResultCount() > 0 ) {
//			FacesContext.getCurrentInstance().addMessage( "",
//					new FacesMessage( FacesMessage.SEVERITY_ERROR, "与其他项目的成交时间过于接近,请修改成交间隔为10分钟以上！", "" ) );
//			return null;
//		}
		
		String result = bulletinService.rechoose(getOldChooseTime(),bulletin);
		return result;
	}
	
	public String cancelCurrent() {
		Bulletin bulletin = getInstance();
		
		if(bulletin.getTradeStatus() != TradeStatus.Agreed) {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "此公告尚未成交，不能作废！", "" ) );
			return null;
		}	
		
		
		String result = bulletinService.cancelCurrent(bulletin,bulletin.getReChooseReason());
		if(StringUtils.isBlank(result)) {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "暂无可顺延中介，请核实！", "" ) );
			return null;
		}
		return result;
	}
	
	public Date getOldChooseTime() {
		return oldChooseTime;
	}

	public void setOldChooseTime(Date oldChooseTime) {
		this.oldChooseTime = oldChooseTime;
	}

	@Inject
	@BulletinRejectEvent
	Event<Bulletin> event;

	public String reject() {
		getInstance().setAuditResult( false );
		getInstance().setAuditor( userService.getLoginedUser().getUsername() );
		getInstance().setAuditTime( new Date() );
		RejectRecord rejectRecord = rejectRecordHome.getInstance();
		getInstance().getHistoryRejectRecords().add( rejectRecord );
		getInstance().setCurrRejectRecord( rejectRecord );
		String result = super.saveAndFlush();
		if ( result.equals( "saved" ) ) {
			event.fire( getInstance() );
			return "rejected";
		}
		return null;
	}

	public void updateSectorStr() {
		TreeNode[] nodes = getSelectedNodes();
		TreeNode[] destNodes = null;
		if ( nodes.length > 0 ) {
			TreeNode firstNode = nodes[0];
			Sector sector = entityManagerDao.find( Sector.class,
					((Map<String, String>) firstNode.getData()).get( "id" ) );
			if ( null == sector.getParentSector() ) {
				destNodes = new TreeNode[nodes.length - 1];
				System.arraycopy( nodes, 1, destNodes, 0, nodes.length - 1 );
			} else {
				destNodes = nodes;
			}
		}
		StringBuilder sb = new StringBuilder();
		if ( null != destNodes ) {
			for ( TreeNode node : destNodes ) {
				Map<String, String> data = (Map<String, String>) node.getData();
				sb.append( data.get( "name" ) );
				sb.append( "," );
			}
			setSectorStr( sb.toString().substring( 0, sb.toString().length() - 1 ) );
		}

	}

	public void chooseSectors() {
		if ( getCurrTemplate().getSectors() != null )
			getCurrTemplate().getSectors().clear();

		TreeNode[] currentTree = getSelectedNodeMap().get( getCurrGroupIndex() ).get( getCurrTemplateIndex() );
		for ( TreeNode treeNode : currentTree ) {
			if ( treeNode.getChildCount() > 0 )
				continue;
			String id = ((HashMap<String, String>) treeNode.getData()).get( "id" );
			addCurrentCertSectorId( id );
		}
	}

	public void addCurrentCertSectorId( String id ) {
		Sector sector = entityManagerDao.find( Sector.class, id );
		if ( !getCurrTemplate().getSectors().contains( sector ) )
			getCurrTemplate().getSectors().add( sector );
	}

	public String applingDone() {
		getInstance().setApplyDone( true );
		getInstance().setApplyDoneTime( new Date() );
		String result = super.saveAndFlush();
		if(RESULT_SAVED.equals(result))return "ApplingDoneTradeList.xhtml?faces-redirect=true&amp;includeViewParams=true";
		else return null;
	}
	@Inject
	AttachmentUtils attachmentUtils;
	public void uploadBulletinPhotos( FileUploadEvent event ) {
		if ( event.getFile() == null )
			return;

		com.ews.onlineexchange.model.Image attr = attachmentUtils.getImageFromUpload(event.getFile());
		attr.generateThumbnail();

		getInstance().getPhotos().add( attr );
		FacesMessage message = new FacesMessage( event.getFile().getFileName() + " 上传成功。" );
		FacesContext.getCurrentInstance().addMessage( null, message );
	}

	public void removeBulletinPhotos( Image photo ) {
		this.getInstance().getPhotos().remove( photo );
	}
	
	public String getRejectReason() {
		return rejectReason;
	}

	public void setRejectReason( String rejectReason ) {
		this.rejectReason = rejectReason;
	}

	public ServiceSupplier getServiceSupplier() {
		return serviceSupplier;
	}

	public void setServiceSupplier( ServiceSupplier serviceSupplier ) {
		this.serviceSupplier = serviceSupplier;
	}

	public Trade getBestChooseTrade() {
		return bestChooseTrade;
	}

	public void setBestChooseTrade( Trade bestChooseTrade ) {
		this.bestChooseTrade = bestChooseTrade;
	}
	
	
	
	public Trade getAssessChooseTrade() {
		return assessChooseTrade;
	}

	public void setAssessChooseTrade(Trade assessChooseTrade) {
		this.assessChooseTrade = assessChooseTrade;
	}

	public Set<TreeNode> getCheckboxSelectedNodes() {
		return checkboxSelectedNodes;
	}

	public void setCheckboxSelectedNodes( Set<TreeNode> checkboxSelectedNodes ) {
		this.checkboxSelectedNodes = checkboxSelectedNodes;
	}

	public String getSectorStr() {
		return sectorStr;
	}

	public void setSectorStr( String sectorStr ) {
		this.sectorStr = sectorStr;
	}

	public TreeNode[] getSelectedNodes() {
		return selectedNodes;
	}

	public void setSelectedNodes( TreeNode[] selectedNodes ) {
		this.selectedNodes = selectedNodes;
	}

	public boolean isDebug() {
		return debug;
	}

	public void setDebug( boolean debug ) {
		this.debug = debug;
	}

	public QualificationGroup getCurrGroup() {
		return currGroup;
	}

	public void setCurrGroup( QualificationGroup currGroup ) {
		this.currGroup = currGroup;
	}

	public AgentService getCurrAgentService() {
		return currAgentService;
	}

	public void setCurrAgentService( AgentService currAgentService ) {
		this.currAgentService = currAgentService;

	}

	public String getCurrAgentServiceIndex() {
		return currAgentServiceIndex;
	}

	public void setCurrAgentServiceIndex( String currAgentServiceIndex ) {
		// List<AgentService> services = getCurrServiceGroup().getAgentServices();
		if ( !StringUtils.isBlank( currAgentServiceIndex ) ) {
			this.currAgentServiceIndex = currAgentServiceIndex;
		}

		if ( !StringUtils.isBlank( getCurrServiceGroupIndex() ) && !StringUtils.isBlank( getCurrAgentServiceIndex() )
				&& this.selectedAgentServiceMap.get( getCurrServiceGroupIndex() ) == null ) {
			this.selectedAgentServiceMap.put( getCurrServiceGroupIndex(), new LinkedHashMap<>() );
		}
	}

	public String getCurrGroupIndex() {
		return currGroupIndex;
	}

	public void setCurrGroupIndex( String currGroupIndex ) {
		this.currGroupIndex = currGroupIndex;
	}

	public QualificationTemplate getCurrTemplate() {
		return currTemplate;
	}

	public String getCurrTemplateIndex() {
		return currTemplateIndex;
	}

	public void setCurrTemplateIndex( String currTemplateIndex ) {
		this.currTemplateIndex = currTemplateIndex;
		if ( this.getSelectedNodeMap().get( getCurrGroupIndex() ) == null ) {
			this.getSelectedNodeMap().put( getCurrGroupIndex(), new LinkedHashMap<>() );
		}
	}

	public Map<String, Map<String, TreeNode>> getRootNodeMap() {
		return rootNodeMap;
	}

	public void setRootNodeMap( Map<String, Map<String, TreeNode>> rootNodeMap ) {
		this.rootNodeMap = rootNodeMap;
	}

	public Map<String, Map<String, TreeNode[]>> getSelectedNodeMap() {
		return selectedNodeMap;
	}

	public void setSelectedNodeMap( Map<String, Map<String, TreeNode[]>> selectedNodeMap ) {
		this.selectedNodeMap = selectedNodeMap;
	}

	public void changeQualificationClass( String groupIndex, String templateIndex ) {
		getRootNodeMap().remove( getCurrGroupIndex() );
		getSelectedNodeMap().remove( getCurrGroupIndex() );
		List<QualificationGroup> groups = getInstance().getQualificationGroup().getQualificationGroups();
		QualificationGroup destGroup = null;
		for ( QualificationGroup qualificationGroup : groups ) {
			if ( qualificationGroup.getGroupIndex().equals( groupIndex ) ) {
				destGroup = qualificationGroup;
			}
		}
		if ( destGroup != null ) {
			List<QualificationTemplate> templates = destGroup.getQualificationTemplates();
			QualificationTemplate destTemplate = null;
			for ( QualificationTemplate qualificationTemplate : templates ) {
				if ( qualificationTemplate.getTemplateIndex().equals( templateIndex ) ) {
					destTemplate = qualificationTemplate;
				}
			}
			if ( destTemplate != null ) {
				destTemplate.setSectors( new ArrayList<Sector>() );
			}
		}
		// getInstance().getQualificationGroup().getQualificationGroups().get(groupIndex).getQualificationTemplates().get(templateIndex).setSectors(new
		// ArrayList<>());
	}

	public Trade getManualChooseTrade() {
		return manualChooseTrade;
	}

	public void setManualChooseTrade( Trade manualChooseTrade ) {
		this.manualChooseTrade = manualChooseTrade;
	}

	public String manualChoose() {
		getInstance().setSuccessTrade( getManualChooseTrade() );
		bulletinService.endBulletinManual( getInstance() );
		return "success";
	}

	@Transient
	public void addEmptyTemplate() {
		// if(getCurrGroup() == null) {
		// setCurrGroup(new QualificationGroup());
		// }
		List<QualificationGroup> groups = getInstance().getQualificationGroup().getQualificationGroups();
		QualificationGroup destGroup = null;
		for ( QualificationGroup qualificationGroup : groups ) {
			if ( qualificationGroup.getGroupIndex().equals( getCurrGroupIndex() ) ) {
				destGroup = qualificationGroup;
			}
		}
		if ( destGroup != null ) {
			QualificationTemplate qualificationTemplate = new QualificationTemplate();
			qualificationTemplate.setTemplateIndex( SystemUUIDUtil.getUUID() );
			destGroup.getQualificationTemplates().add( qualificationTemplate );
		}
		// getCurrGroup().getQualificationTemplates().add(new QualificationTemplate());
	}

	public void removeQualificationTemplate() {
		if ( getSelectedNodeMap() != null ) {
			Map<String, TreeNode[]> map = getSelectedNodeMap().get( getCurrGroupIndex() );
			if ( map != null )
				map.remove( getCurrTemplateIndex() );
		}
		QualificationGroup destGroup = null;
		List<QualificationGroup> groups = getInstance().getQualificationGroup().getQualificationGroups();
		for ( QualificationGroup qualificationGroup : groups ) {
			if ( qualificationGroup.getGroupIndex().equals( getCurrGroupIndex() ) ) {
				destGroup = qualificationGroup;
			}
		}
		if ( destGroup != null ) {
			List<QualificationTemplate> templates = destGroup.getQualificationTemplates();
			QualificationTemplate removeTemplate = null;
			for ( QualificationTemplate qualificationTemplate : templates ) {
				if ( qualificationTemplate.getTemplateIndex().equals( getCurrTemplateIndex() ) ) {
					removeTemplate = qualificationTemplate;
				}
			}
			if ( removeTemplate != null ) {
				templates.remove( removeTemplate );
			}
		}

		// getCurrGroup().removeQualificationTemplate(getCurrTemplateIndex());
	}

	public void removeAgentService() {
		QualificationGroup destGroup = null;
		List<QualificationGroup> groups = getInstance().getQualificationGroup().getAgentServiceGroups();
		for ( QualificationGroup qualificationGroup : groups ) {
			if ( qualificationGroup.getGroupIndex() == getCurrServiceGroupIndex() ) {
				destGroup = qualificationGroup;
			}
		}
		if ( destGroup != null ) {
			List<AgentService> services = destGroup.getAgentServices();
			AgentService removeService = null;
			for ( AgentService service : services ) {
				if ( service.getServiceIndex() == getCurrAgentServiceIndex() ) {
					removeService = service;
				}
			}
			if ( removeService != null ) {
				services.remove( removeService );
				if ( services.size() == 0 ) {
					groups.remove( destGroup );
				}
			}
		}

	}

	public void addEmptyAgentService() {
		QualificationGroup destGroup = null;
		List<QualificationGroup> groups = getInstance().getQualificationGroup().getAgentServiceGroups();
		for ( QualificationGroup qualificationGroup : groups ) {
			if ( qualificationGroup.getGroupIndex() == getCurrServiceGroupIndex() ) {
				destGroup = qualificationGroup;
			}
		}
		if ( destGroup != null ) {
			AgentService service = new AgentService();
			service.setServiceIndex( SystemUUIDUtil.getUUID() );
			destGroup.getAgentServices().add( service );
		}
		// getCurrServiceGroup().getAgentServices().add(new AgentService());
	}

	public void removeGroup() {
		QualificationGroup destGroup = null;
		List<QualificationGroup> groups = getInstance().getQualificationGroup().getQualificationGroups();
		for ( QualificationGroup qualificationGroup : groups ) {
			if ( qualificationGroup.getGroupIndex().equals( getCurrGroupIndex() ) ) {
				destGroup = qualificationGroup;
			}
		}
		if ( destGroup != null ) {
			groups.remove( destGroup );
		}

		this.setCurrGroup( null );
		this.setCurrGroupIndex( "" );
		this.setCurrTemplate( null );
		this.setCurrTemplateIndex( "" );
	}

	public void removeAgentServiceGroup() {
		List<QualificationGroup> groups = getInstance().getQualificationGroup().getAgentServiceGroups();
		QualificationGroup removeGroup = null;
		for ( QualificationGroup qualificationGroup : groups ) {
			if ( qualificationGroup.getGroupIndex().equals( getCurrServiceGroupIndex() ) ) {
				removeGroup = qualificationGroup;
			}
		}
		if ( removeGroup != null ) {
			groups.remove( removeGroup );
		}
		// getInstance().getQualificationGroup().getAgentServiceGroups().remove(getCurrServiceGroupIndex().intValue());
		this.setCurrServiceGroup( null );
		this.setCurrServiceGroupIndex( "" );
		this.setCurrAgentService( null );
		this.setCurrAgentServiceIndex( "" );
	}

	public StreamedContent getPhotoStreamedContent( Image image ) {
		if ( image == null )
			return null;
		return new DefaultStreamedContent( new ByteArrayInputStream( image.getThumbnailData() ) );
	}

	public QualificationGroup getCurrServiceGroup() {
		return currServiceGroup;
	}

	public void setCurrServiceGroup( QualificationGroup currServiceGroup ) {
		this.currServiceGroup = currServiceGroup;
	}

	public void setCurrTemplate( QualificationTemplate currTemplate ) {
		this.currTemplate = currTemplate;
	}

	public String getCurrServiceGroupIndex() {
		return currServiceGroupIndex;
	}

	public void setCurrServiceGroupIndex( String currServiceGroupIndex ) {

		this.currServiceGroupIndex = currServiceGroupIndex;
		if ( !StringUtils.isBlank( getCurrServiceGroupIndex() ) && !StringUtils.isBlank( getCurrAgentServiceIndex() )
				&& this.selectedAgentServiceMap.get( getCurrServiceGroupIndex() ) == null ) {
			this.selectedAgentServiceMap.put( getCurrServiceGroupIndex(), new LinkedHashMap<>() );
		}
	}

	public Map<String, Map<String, AgentService>> getSelectedAgentServiceMap() {
		return selectedAgentServiceMap;
	}

	public void setSelectedAgentServiceMap( Map<String, Map<String, AgentService>> selectedAgentServiceMap ) {
		this.selectedAgentServiceMap = selectedAgentServiceMap;
	}

	public void uploadAttachment( FileUploadEvent event ) {
		if ( event.getFile() == null )
			return;

		Attachment attr = attachmentUtils.getAttachmentFromUpload(event.getFile());
		getInstance().getAttachments().add( attr );
		FacesMessage message = new FacesMessage( event.getFile().getFileName() + " 上传成功。" );
		FacesContext.getCurrentInstance().addMessage( null, message );
	}

	public void removeAttachment( Attachment attachment ) {
		getInstance().getAttachments().remove( attachment );
	}
	
	public void uploadAppliedDoneAttachment( FileUploadEvent event ) {
		if ( event.getFile() == null )
			return;

		Attachment attr = attachmentUtils.getAttachmentFromUpload(event.getFile());

		getInstance().getAppliedDoneAttachments().add( attr );
		FacesMessage message = new FacesMessage( event.getFile().getFileName() + " 上传成功。" );
		FacesContext.getCurrentInstance().addMessage( null, message );
	}

	public void removeAppliedDoneAttachment( Attachment attachment ) {
		getInstance().getAppliedDoneAttachments().remove( attachment );
	}
	
	public void uploadAssessDoneAttachment( FileUploadEvent event ) {
		if ( event.getFile() == null )
			return;

		Attachment attr = attachmentUtils.getAttachmentFromUpload(event.getFile());

		getInstance().getAssessAttachments().add( attr );
		FacesMessage message = new FacesMessage( event.getFile().getFileName() + " 上传成功。" );
		FacesContext.getCurrentInstance().addMessage( null, message );
	}

	public void removeAssessAttachment( Attachment attachment ) {
		getInstance().getAssessAttachments().remove( attachment );
	}
	
	public void uploadAssessImage( FileUploadEvent event ) {
		if ( event.getFile() == null )
			return;

		Image attr = attachmentUtils.getImageFromUpload(event.getFile());;
		attr.generateThumbnail();
		getInstance().getAssessImages().add( attr );
		FacesMessage message = new FacesMessage( event.getFile().getFileName() + " 上传成功。" );
		FacesContext.getCurrentInstance().addMessage( null, message );
	}

	public void removeAssessImage( Image photo ) {
		this.getInstance().getAssessImages().remove( photo );
	}
	
	public void updateAgentService() {
		List<AgentService> services = getCurrServiceGroup().getAgentServices();
		int serviceIndex = 11111;// 临时设置一个足够大的值
		for ( int i = 0; i < services.size(); i++ ) {
			if ( services.get( i ).getServiceIndex().equals( getCurrAgentServiceIndex() ) ) {
				serviceIndex = i;
			}
		}
		if ( serviceIndex != 11111 ) {
			AgentService service = selectedAgentServiceMap.get( currServiceGroupIndex )
					.get( getCurrAgentServiceIndex() );
			service.setServiceIndex( getCurrAgentServiceIndex() );
			getCurrServiceGroup().getAgentServices().set( serviceIndex, service );
		}
	}

	public void onRowSelect( SelectEvent event ) {
		AgentService service = (AgentService) event.getObject();
		service.setServiceIndex( getCurrAgentServiceIndex() );
		if ( null == getSelectedAgentServiceMap().get( getCurrServiceGroupIndex() ) ) {
			Map<String, AgentService> serviceMap = new HashMap<String, AgentService>();
			serviceMap.put( getCurrAgentServiceIndex(), service );
			getSelectedAgentServiceMap().put( getCurrServiceGroupIndex(), serviceMap );
		} else {
			getSelectedAgentServiceMap().get( getCurrServiceGroupIndex() ).put( getCurrAgentServiceIndex(), service );
		}

		// getCurrServiceGroup().getAgentServices().set(getCurrAgentServiceIndex(),
		// service);
	}

	public boolean canApply() {
		loadInstance();
		if ( getInstance().getEndingApplyTime().before( new Date() ) )
			return false;
		User user = userService.getLoginedUser();

		if ( user != null ) {
			if ( recordService.isExistSupplierInRecord( user.getId() ) ) {
				return false;
			}
						
			serviceSupplierHome.setId( user.getId() );
			serviceSupplierHome.initConversation();
		}

		// List<Trade> trades = getInstance().getTrades();
		// if(trades.size() == 0) {
		//
		// }
		List<Trade> trades = tradeService.getTradesByBulletinId( getInstance().getId() );

		// 最外层关系
		Relation relation = getInstance().getQualificationGroup().getRelation();
		if ( user != null && user instanceof ServiceSupplier ) {
			ServiceSupplier supplier = serviceSupplierHome.getInstance();
			if ( supplier.getAuditted() == null || !supplier.getAuditted() )
				return false;
			if ( !supplier.isValid() )
				return false;
			/*
			 * 信用分数不够不能报名
			 */
			if ( supplier.getCreditScore().compareTo( getInstance().getCreditScoreLimit() ) < 0 ) {
				return false;
			}
			for ( Trade trade : trades ) {
				ServiceSupplier tradeSupplier = trade.getSupplier();
				if ( tradeSupplier.getId().equals( supplier.getId() ) )
					return false;
			}
			List<MainBusiness> mainBusinesses = supplier.getMainBusinesses();
			List<AgentService> supplierAgentService = new ArrayList<>();// 中介服务事项
			for ( MainBusiness _mb : mainBusinesses ) {
				supplierAgentService.add( _mb.getAgentService() );
			}
			List<QualificationGroup> serviceGroups = getInstance().getQualificationGroup().getAgentServiceGroups();// 公告服务事项要求
			List<QualificationGroup> qualificationGroups = getInstance().getQualificationGroup()
					.getQualificationGroups();// 公告资质要求
			List<QualificationCert> certs = supplier.getCerts();
			List<QualificationTemplate> supplierTemplates = new ArrayList<>();// 中介资质
			for ( QualificationCert qualificationCert : certs ) {
				if ( qualificationCert.isValid() && qualificationCert.getAuditResult() ) {
					supplierTemplates.addAll( qualificationCert.getQualificationTemplates() );
				}
			}

			boolean agentServiceFlag = true;
			for ( QualificationGroup serviceGroup : serviceGroups ) {
				boolean isVerified = isVerifiedAgentServiceGroup( serviceGroup, supplierAgentService );
				if ( serviceGroup.getRelation().equals( Relation.And ) ) {
					agentServiceFlag = agentServiceFlag && isVerified;
				} else {
					agentServiceFlag = agentServiceFlag || isVerified;
				}
			}

			// if(!agentServiceFlag) return false;

			if ( qualificationGroups.size() > 0 && supplierTemplates.size() == 0 && relation.equals( Relation.And ) ) {
				System.out.println( "全部符合：公告有资质要求但是中介一个资质都没" );
				return false;
			}

			boolean isQualificationVerifed = true;
			for ( QualificationGroup qualificationGroup : qualificationGroups ) {
				boolean isVerified = isVerifiedQualificationGroup( qualificationGroup, supplierTemplates );
				if ( qualificationGroup.getRelation().equals( Relation.And ) ) {

					isQualificationVerifed = isQualificationVerifed && isVerified;
				} else {

					isQualificationVerifed = isQualificationVerifed || isVerified;
				}
			}

			// return isQualificationVerifed;

			if ( relation.equals( Relation.And ) ) {
				System.out.println( "And=" );
				System.out.println( agentServiceFlag && isQualificationVerifed );
				return agentServiceFlag && isQualificationVerifed;
			} else {
				System.out.println( "Or=" );
				System.out.println( agentServiceFlag || isQualificationVerifed );
				return agentServiceFlag || isQualificationVerifed;
			}
		} else
			return false;

	}

	public String applyTrade() {
		
		try {
			Bulletin bulletin = getInstance();
			ServiceSupplier loginedUser = (ServiceSupplier)userService.getLoginedUser();
			tradeService.generateTrade(bulletin, loginedUser);
			return "/business/supplier/UnapplyTradeList.xhtml";
//			supplierApplyService.applyTrade( instance );
//			FacesContext.getCurrentInstance().addMessage( "bulletinEndingApplyTime",
//					new FacesMessage( FacesMessage.SEVERITY_INFO, "报名成功！", "" ) );
//		} catch ( ConflictingSupplierException e ) {
//			String message = "您已经中选了【%s】项目，按照管理办法您不能参与本项目的选取!";
//			message = String.format( message, e.getMessage() );
//			FacesContext.getCurrentInstance().addMessage( "",
//					new FacesMessage( FacesMessage.SEVERITY_ERROR, message, "" ) );
//			return;
		} catch ( Exception e ) {
			e.printStackTrace();
			FacesContext.getCurrentInstance().addMessage( "bulletinEndingApplyTime",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "报名出错，请查看是否重复报名!", "" ) );
			return null;
		}

	}

	private boolean isVerifiedAgentServiceGroup( QualificationGroup serviceGroup,
			List<AgentService> supplierAgentService ) {
		List<AgentService> bulletinAgentServices = serviceGroup.getAgentServices();
		boolean flag = false;
		for ( AgentService agentService2 : bulletinAgentServices ) {
			for ( AgentService agentService : supplierAgentService ) {
				if ( agentService2.getId().equals( agentService.getId() ) ) {
					flag = true;
					break;
				}
			}
			if ( !flag )
				return false;
		}
		return true;
	}

	private boolean isVerifiedQualificationGroup( QualificationGroup group,
			List<QualificationTemplate> supplierTemplates ) {
		List<QualificationTemplate> templates = group.getQualificationTemplates();
		for ( QualificationTemplate qualificationTemplate : templates ) {
			boolean secordCertVerified = false;
			List<Sector> sectors = qualificationTemplate.getSectors();
			QualificationClass qClass = qualificationTemplate.getQualificationClass();
			QualificationLevel level = qualificationTemplate.getQualificationLevel();
			for ( QualificationTemplate supplierTemplate : supplierTemplates ) {
				List<Sector> supplierSectors = supplierTemplate.getSectors();
				QualificationClass supplierQClass = supplierTemplate.getQualificationClass();
				QualificationLevel supplierLevel = supplierTemplate.getQualificationLevel();
				if ( supplierSectors.containsAll( sectors ) && qClass.getId().equals( supplierQClass.getId() )
						&& (supplierLevel.getValue() <= level.getValue()) ) {
					secordCertVerified = true;
					break;
				}
			}
			if ( !secordCertVerified )
				return false;

		}
		return true;
	}
	
	/**是否可以报价 
	 * @return
	 */
	public boolean canOfferPrice() {
		Bulletin instance = loadInstance();
		if ( instance.getChooseTime().before( new Date() ) )//超时
			return false;
		User user = userService.getLoginedUser();
		//是中介、 已经报名、竞价选取
		if(!(user instanceof ServiceSupplier && (instance.getWayOfChoose().equals(ChooseType.Price) ||instance.getWayOfChoose().equals(ChooseType.Average)) 
				&& 	BulletinService.isInVerifiedTrades(user,instance.getVerifiedTrades())) ) 
		return false;
		
		return true;
	}

	public String initSuppliers() {
		// Map<String, String> params =
		// FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
		suppliers = candidateSupplierSelector.getResultList( getInstance());
		System.out.println( suppliers );

		return "get";

	}

	public List<ServiceSupplier> getSuppliers() {
		return suppliers;
	}

	public void setSuppliers( List<ServiceSupplier> suppliers ) {
		this.suppliers = suppliers;
	}

	public String getSupplierNames() {
		StringBuilder sb = new StringBuilder();
		for ( Trade trade : getInstance().getVerifiedTrades() ) {
			sb.append( trade.getSupplier().getCnname() );
			sb.append( "、" );
		}
		if ( sb.length() > 1 )
			return sb.substring( 0, sb.length() - 1 );
		else
			return sb.toString();
	}

	private String smsContent;

	public String getSmsContent() {
		return smsContent;
	}

	public void setSmsContent( String smsContent ) {
		this.smsContent = smsContent;
	}

	public String sendSelfSms() {
		if ( StringUtils.isNoneBlank( smsContent ) ) {
			for ( Trade trade : getInstance().getVerifiedTrades() ) {
				smsService.sendSmsToSupplier( trade, smsContent );
			}
		}
		return "BulletinList.xhtml?faces-redirect=true&amp;includeViewParams=true&amp;firstResult=0";

	}

	public Date getLastBuyerUpdateTime() {
		return lastBuyerUpdateTime;
	}

	public void setLastBuyerUpdateTime(Date lastBuyerUpdateTime) {
		this.lastBuyerUpdateTime = lastBuyerUpdateTime;
	}
	
	
	
	@Inject
	BestTradeEvaluationOfBulletinList bestTradeEvaluationOfBulletinList;
	public boolean isCanPublishBestChooseResult() {
		if ( !getInstance().getWayOfChoose().equals( ChooseType.Best ) ) {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "本功能仅适用于择优选取候选中介评选！", "" ) );
			return false;
		}
		
		if ( !getInstance().getTradeStatus().equals( TradeStatus.Waiting ) ) {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "公告状态未非待选状态！", "" ) );
			return false;
		}
		
		List<Trade> bestTrades = getInstance().getBestTrades();
		if ( bestTradeEvaluationOfBulletinList.getResultCount() < bestTrades.size() * getInstance().getDefs().size() ) {
			FacesContext.getCurrentInstance().addMessage( "",
					new FacesMessage( FacesMessage.SEVERITY_ERROR, "部分候选中介尚未完成审核！", "" ) );
			return false;
		}
		
		return true;
	}
	
	public String buyerReportBestChooseEvaluation() {
		Task task = taskService.createTaskQuery().processInstanceBusinessKey( getInstance().getId() ).list().get( 0 );
		taskService.claim( task.getId(), userService.getLoginedUser().getUsername() );
		taskService.complete( task.getId() );
		return "ok";
	}
	
	public String publishBestChooseResult() {
		if ( !isCanPublishBestChooseResult() ) {
			return null;
		}
		
		List<Trade> bestTrades = getInstance().getBestTrades();
		Collections.sort( bestTrades, new Comparator<Trade>() {
			@Override
			public int compare( Trade o1, Trade o2 ) {				
				return o1.getTradeReportData().getSumScore().compareTo( o2.getTradeReportData().getSumScore() );
			}
		} );
		
//		bulletinService.auditBestChoose( getInstance(), bestTrades.get( bestTrades.size() - 1 ) );
		getInstance().setSuccessTrade( bestTrades.get( bestTrades.size() - 1 ) );
		getInstance().setTradeStatus(TradeStatus.Agreed);
		Calendar cal = Calendar.getInstance();
		getInstance().setOverTime(cal.getTime());
		getInstance().setOverYear(cal.get(Calendar.YEAR));
		getInstance().setOverMonth(cal.get(Calendar.MONTH) + 1);
		getInstance().setOver(true);
		getInstance().setPublished( true );
		getEntityManager().merge( getInstance() );
		if (!conversation.isTransient())
			conversation.end();
		bulletinAgreeEvent.fire( getInstance() );
		return "BestChooseList.xhtml";
	}
	
	public void assessChooseAuditUploadImage(FileUploadEvent event) {
		if (event.getFile() == null)
			return ;
		Image image = attachmentUtils.getImageFromUpload(event.getFile());
		getInstance().getAssessImages().add(image);
		FacesMessage message = new FacesMessage(image.getFilename() + " 上传成功。");
        FacesContext.getCurrentInstance().addMessage(null, message);
	}
	
	public void assessChooseAuditRemoveImage(int index) {
		getInstance().getAssessImages().remove(index);
	}
	
	public void assessChooseAuditUploadAttachments(FileUploadEvent event) {
		if (event.getFile() == null)
			return ;
		
		Attachment attr  = attachmentUtils.getAttachmentFromUpload(event.getFile());
		
		getInstance().getAssessAttachments().add(attr);
		FacesMessage message = new FacesMessage(event.getFile().getFileName() + " 上传成功。");
        FacesContext.getCurrentInstance().addMessage(null, message);
	}
	
	public void assessChooseAuditRemoveAttachment(int index) {
		getInstance().getAssessAttachments().remove(index);
	}

	public String getSuccessTradeId() {
		return successTradeId;
	}

	public void setSuccessTradeId( String successTradeId ) {
		this.successTradeId = successTradeId;
	}

	public String getConflictBulletinId() {
		return conflictBulletinId;
	}

	public void setConflictBulletinId( String conflictBulletinId ) {
		this.conflictBulletinId = conflictBulletinId;
	}
	
	private Date	endingApplyTime;
	private Date	chooseTime;
	public Date getEndingApplyTime() {
		return endingApplyTime;
	}

	public void setEndingApplyTime( Date endingApplyTime ) {
		this.endingApplyTime = endingApplyTime;
	}

	public Date getChooseTime() {
		return chooseTime;
	}

	public void setChooseTime( Date chooseTime ) {
		this.chooseTime = chooseTime;
	}

	public void suggestTime() {
		Calendar oneDayLater = Calendar.getInstance();
		oneDayLater.add( Calendar.DAY_OF_MONTH, 1 );
		oneDayLater.set( Calendar.SECOND, 0 );
		oneDayLater.set( Calendar.MILLISECOND, 0 );
		int minute = oneDayLater.get( Calendar.MINUTE );
		int suggestMinute = 15 - minute % 15;
		oneDayLater.set( Calendar.MINUTE, minute + suggestMinute );
		
		Calendar lastEndingApplyTime = queryLastEndingApplyTime();
		lastEndingApplyTime.add( Calendar.MINUTE, 30 );
		
		if ( lastEndingApplyTime.after( oneDayLater ) ) { // 说明当天已经有公告审核过了
			this.setEndingApplyTime( lastEndingApplyTime.getTime() );
			lastEndingApplyTime.add( Calendar.MINUTE, 30 );
			this.setChooseTime( lastEndingApplyTime.getTime() );
		} else {
			this.setEndingApplyTime( oneDayLater.getTime() );
			oneDayLater.add( Calendar.MINUTE, 30 );
			this.setChooseTime( oneDayLater.getTime() );
		}
	}

	private static final String QUERY_MAX_ENDING_APPLY_TIME_EQL = ""
			+ "	SELECT		MAX(b.endingApplyTime) "
			+ "	FROM		Bulletin b	";
	private Calendar queryLastEndingApplyTime() {
		Query query = getEntityManagerDao().getEntityManager().createQuery( QUERY_MAX_ENDING_APPLY_TIME_EQL );
		List<Date> resultList = query.getResultList();
		Calendar cal = Calendar.getInstance();

		if ( resultList.size() > 0  && resultList.get( 0 ) != null) {
			cal.setTime( resultList.get( 0 ) );
		}
		return cal;
	}

	public String getRefuseReason() {
		return refuseReason;
	}

	public void setRefuseReason( String refuseReason ) {
		this.refuseReason = refuseReason;
	}
	private final static String[] reqNames = {"社保材料","业绩材料","人员证书材料","其他材料"};
	public void addDefaultBestChooseRequirements(ValueChangeEvent event) {
		List<RequirementDefination> defs = new ArrayList<>();
		if((ChooseType)event.getNewValue() == ChooseType.Best) {
			for (String str : reqNames) {
				RequirementDefination def = new RequirementDefination(str,true);
				defs.add(def);
			}
		}
		getInstance().setDefs(defs);
	}
	
}
